home *** CD-ROM | disk | FTP | other *** search
/ ftp.mactech.com 2010 / ftp.mactech.com.tar / ftp.mactech.com / machack / Hacks95 / Aaron 1.0b3.sit / Aaron 1.0b3 / Aaron Source / ShowInitIcon 1.0 / ShowInitIcon.p < prev    next >
Text File  |  1995-06-24  |  8KB  |  213 lines

  1. unit ShowInitIcon;
  2.  
  3. { ShowInitIcon - version 1.0, May 8th, 1995 }
  4. { This code is intended to let INIT writers easily display an icon at startup time. }
  5. { View in Geneva 9pt, 4-space tabs }
  6.  
  7. { Written by: Peter N Lewis <peter@mail.peter.com.au>, Jim Walker <JWWalker@aol.com> }
  8. { and François Pottier <pottier@dmi.ens.fr>, with thanks to previous ShowINIT authors. }
  9. { Send comments and bug reports to François Pottier. }
  10.  
  11. { This version features: }
  12. { - Short and readable code. }
  13. { - Correctly wraps around when more than one row of icons has been displayed. }
  14. { - works with System 6 }
  15. { - Built with Think Pascal. Should work with other headers/compilers. }
  16.  
  17. interface
  18.  
  19.     uses
  20.         Types;
  21.  
  22. { --------------------------------------------------------------------------------------------------------------------- }
  23. { Set this to 1 if you want to compile this file into a stand-alone resource. (see notes below) }
  24.  
  25. {$SETC STANDALONE:=0}
  26.  
  27. {$IFC STANDALONE}
  28.     procedure Main (iconFamilyID: integer; advance: Boolean);
  29. {$ELSEC}
  30.     procedure ShowInitIcon (iconFamilyID: integer; advance: Boolean);
  31. {$ENDC}
  32.  
  33. implementation
  34.  
  35.     uses
  36.         Icons, OSUtils, Resources, Memory, QuickDraw;
  37.  
  38. { --------------------------------------------------------------------------------------------------------------------- }
  39. { The ShowINIT mechanism works by having each INIT read/write data from these globals. }
  40.  
  41.     type
  42.         LMShowInitRecord = packed record
  43.                 LMVCheckSum: integer;
  44.                 LMVCoord: integer;
  45.                 LMHCoord: integer;
  46.                 LMHCheckSum: integer;
  47.             end;
  48.         LMShowInitRecordPtr = ^LMShowInitRecord;
  49.  
  50.     const
  51.         LMShowInitRecordAddr = $928;                                                        { Low Memory address of record }
  52.  
  53. { --------------------------------------------------------------------------------------------------------------------- }
  54. { Main must be the first function in the file for THINK Pascal's "Custom header" option to work. }
  55.  
  56.     function CheckSum (x: integer): integer;
  57.     forward;
  58.     procedure ComputeIconRect (var iconRect: Rect; var bounds: Rect);
  59.     forward;
  60.     procedure AdvanceIconPosition (var iconRect: Rect);
  61.     forward;
  62.     procedure DrawBWIcon (iconID: integer; var iconRect: Rect);
  63.     forward;
  64.  
  65. { --------------------------------------------------------------------------------------------------------------------- }
  66. { Main routine. }
  67.  
  68. { You will probably need this definition of QDGlobals if you use Think Pascal. CodeWarrior doesn't need it. }
  69. {$IFC 1}
  70.     type
  71.         QDGlobals = record
  72.                 privates: packed array[1..76] of Byte;
  73.                 randSeed: longint;
  74.                 screenBits: BitMap;
  75.                 arrow: Cursor;
  76.                 dkGray, ltGray, gray, black, white: Pattern;
  77.                 thePort: GrafPtr;
  78.             end;
  79. {$ENDC}
  80.  
  81.     type
  82.         QDStorage = record
  83.                 qd: QDGlobals;                                                                            { Storage for the QuickDraw globals }
  84.                 qdGlobalsPtr: Ptr;                                                                        { A5 points to this place; it will contain a pointer to qd }
  85.             end;
  86.  
  87. {$IFC STANDALONE}
  88.     procedure Main (iconFamilyID: integer; advance: Boolean);
  89. {$ELSEC}
  90.         procedure ShowInitIcon (iconFamilyID: integer; advance: Boolean);
  91. {$ENDC}
  92.             var
  93.                 oldA5: longInt;
  94.                 qds: QDStorage;                                                                        { Fake QD globals }
  95.                 colorPort: CGrafPort;
  96.                 bwPort: GrafPort;
  97.                 destRect: Rect;
  98.                 environment: SysEnvRec;                                                            { Machine configuration. }
  99.                 junk: OSErr;
  100.  
  101.         begin
  102.  
  103.             oldA5 := SetA5(longInt(@qds.qdGlobalsPtr));                                    { Tell A5 to point to the end of the fake QD Globals }
  104.             InitGraf(@qds.qd.thePort);                                                            { Initialize the fake QD Globals }
  105.  
  106.             junk := SysEnvirons(curSysEnvVers, environment);                        { Find out what kind of machine this is}
  107.  
  108.             ComputeIconRect(destRect, qds.qd.screenBits.bounds);                    { Compute where the icon should be drawn }
  109.  
  110.             if (environment.systemVersion >= $0700) & environment.hasColorQD then begin
  111.                 OpenCPort(@colorPort);
  112.                 junk := PlotIconID(destRect, atNone, ttNone, iconFamilyID);
  113.                 CloseCPort(@colorPort);
  114.             end
  115.             else begin
  116.                 OpenPort(@bwPort);
  117.                 DrawBWIcon(iconFamilyID, destRect);
  118.                 ClosePort(@bwPort);
  119.             end;
  120.  
  121.             if advance then
  122.                 AdvanceIconPosition(destRect);
  123.  
  124.             oldA5 := SetA5(oldA5);                                                                 { Restore A5 to its previous value }
  125.         end;
  126.  
  127. { --------------------------------------------------------------------------------------------------------------------- }
  128. { A checksum is used to make sure that the data in there was left by another ShowINIT-aware INIT. }
  129.  
  130.         function CheckSum (x: integer): integer;
  131.         begin
  132.             CheckSum := BXOR(BOR(BSL(x, 1), BSR(x, 15)), $1021);
  133.         end;
  134.  
  135. { --------------------------------------------------------------------------------------------------------------------- }
  136. { ComputeIconRect computes where the icon should be displayed. }
  137.  
  138.         procedure ComputeIconRect (var iconRect: Rect; var bounds: Rect);
  139.             var
  140.                 lmp: LMShowInitRecordPtr;
  141.         begin
  142.             lmp := LMShowInitRecordPtr(LMShowInitRecordAddr);
  143.  
  144.             if (CheckSum(lmp^.LMHCoord) <> lmp^.LMHCheckSum) then            { If we are first, we need to initialize the shared data. }
  145.                 lmp^.LMHCoord := 8;
  146.             if (CheckSum(lmp^.LMVCoord) <> lmp^.LMVCheckSum) then
  147.                 lmp^.LMVCoord := bounds.bottom - 40;
  148.  
  149.             if (lmp^.LMHCoord + 34 > bounds.right) then begin                        { Check whether we must wrap }
  150.                 iconRect.left := 8;
  151.                 iconRect.top := lmp^.LMVCoord - 40;
  152.             end
  153.             else begin
  154.                 iconRect.left := lmp^.LMHCoord;
  155.                 iconRect.top := lmp^.LMVCoord;
  156.             end;
  157.  
  158.             iconRect.right := iconRect.left + 32;
  159.             iconRect.bottom := iconRect.top + 32;
  160.         end;
  161.  
  162. { AdvanceIconPosition updates the shared globals so that the next icon will draw its icon next to ours. }
  163.  
  164.         procedure AdvanceIconPosition (var iconRect: Rect);
  165.             var
  166.                 lmp: LMShowInitRecordPtr;
  167.         begin
  168.             lmp := LMShowInitRecordPtr(LMShowInitRecordAddr);
  169.             lmp^.LMHCoord := iconRect.left + 40;                                            { Update the shared data }
  170.             lmp^.LMVCoord := iconRect.top;
  171.             lmp^.LMHCheckSum := CheckSum(lmp^.LMHCoord);
  172.             lmp^.LMVCheckSum := CheckSum(lmp^.LMVCoord);
  173.         end;
  174.  
  175. { DrawBWIcon draws the 'ICN#' member of the icon family. It works under System 6. }
  176.  
  177.         procedure DrawBWIcon (iconID: integer; var iconRect: Rect);
  178.             var
  179.                 icon: Handle;
  180.                 source, destination: BitMap;
  181.                 port: GrafPtr;
  182.         begin
  183.             icon := Get1Resource('ICN#', iconId);
  184.             if (icon <> nil) then begin
  185.                 HLock(icon);
  186.                                                                                                                 { Prepare the source and destination bitmaps. }
  187.                 source.baseAddr := Ptr(longInt(icon^) + 128);                            { Mask address. }
  188.                 source.rowBytes := 4;
  189.                 SetRect(source.bounds, 0, 0, 32, 32);
  190.                 GetPort(port);
  191.                 destination := port^.portBits;
  192.                                                                                                                 { Transfer the mask. }
  193.                 CopyBits(source, destination, source.bounds, iconRect, srcBic, nil);
  194.                                                                                                                 { Then the icon. }
  195.                 source.baseAddr := icon^;
  196.                 CopyBits(source, destination, source.bounds, iconRect, srcOr, nil);
  197.             end;
  198.         end;
  199.  
  200. { --------------------------------------------------------------------------------------------------------------------- }
  201. { Notes }
  202.  
  203. { Checking for PlotIconID: }
  204. { We (PNL) now check for system 7 and colour QD, and use colour graf ports and PlotIconID only if both are true }
  205. { Otherwise we use B&W grafport and draw using PlotBWIcon. }
  206.  
  207. { Should I use it as a standalone code resource or link it into my INIT? }
  208. { I recommend linking the code to your INIT resource, because it's easier and cleaner, *provided* that your INIT resource is }
  209. { written properly, that is, it is destroyed once startup is over. If your INIT installs trap patches, then the code for the trap }
  210. { patches should be compiled into a separate resource (or code fragment, on the PowerPC) and only the code for the patches }
  211. { should remain resident. Filling the System heap with old INIT code isn't cool. }
  212.  
  213.         end.